#include "RoadLocationLayout.h"

#include <QLayout>
#include <QHBoxLayout>
#include <QLabel>

#include <QLineEdit>
#include <QComboBox>
#include <QPushButton>
#include <QPoint>
#include <QMessageBox>
#include <QTimer>

#include <QFontDatabase>

#include <QDebug>


#include "../../../uitools/IdRootMenu.h"
#include "../../../uitools/vhc/constview4fun.h"
#include "../../../uitools/vhc/constview4id.h"

#include "../../../rwidgets/kebtn/KeTogLabelIcon.h"
#include "../../../rwidgets/ketoast/kelabeltoast.h"

#include "mcore/tools/EditWidget.h"
#include "mcore/tools/identify/IdentifyPointSimple.h"
#include "mcore/tools/mutils/DistanceBorderByPoint.h"
#include "mcore/tools/mutils/PointDistanceResult.h"
#include "mcore/kenormalmacrovar.h"

#include "keconst/ConstTeNormal.h"

#include "mcore/map/EarthMapConst.h"

#include <geos/operation/distance/DistanceOp.h>

#include "kepinyinsimple.h"

#define LeftPadding 4
#define HeightSpace 20

#define HeightGridItem_Root 34
#define MinWidthComboxRx 240
#define MinHeightComboxRx 26

#define MinHeightQPushButton  30

#define Heigth_Tri_Toast  8
#define Width_Tri_Toast  8
#define LeftPadding_Rect_Toast  16


#define LeftPaddingView_Toast  8
#define TopPaddingView_Toast  8
#define RightPaddingView_Toast  8
#define BottomPaddingView_Toast  8

/*
 * bool compare_int(int  &lhs, int  & rhs)
{
    return  lhs > rhs;
}
bool compare_first_letter(const std::unique_ptr<std::string > &lhs, const std::unique_ptr<std::string > & rhs)
{
    return  ((*lhs) < (*rhs));
}

bool compare_unique_ptr_int(std::unique_ptr<int > &lhs,std::unique_ptr<int > & rhs)
{
    return  *lhs < *rhs;
}
*/
static bool compare_by_letter(const kepen::kemod::RoadBean* lhs, const kepen::kemod::RoadBean*  rhs)
{
    //名称中，以字母开头的路名称，由于都是‘大写字母’，因此，自然比较汉语开始的，位置靠前

    const QString &a = lhs->pinyin;
    const QString &b = rhs->pinyin;
    if(a.isEmpty() &&b.isEmpty()){
        return false;
    }else if(a.isEmpty()){
        return true;
    }else if(b.isEmpty()){
        return false;
    }else
    {
        ushort ch_a,ch_b;
        int r;
        qsizetype len_a, len_b, len_min, j;
        const ushort *val_a = a.utf16();
        const ushort *val_b = b.utf16();
        len_a = a.length();
        len_b = b.length();
        len_min = std::min(len_a, len_b);

        r = 0;
        j = 0;
        for (; j < len_min; ++j) {
            ch_a = val_a[j];
            ch_b = val_b[j];
            if (ch_a < ch_b) {
                r = -1;
                break;
            } else if (ch_a > ch_b) {
                r = 1;
                break;
            }
        }

        if (0 == r) {
            if (len_a < len_b) {
                r = -1;

            } else if (len_a > len_b) {
                r = 1;
            }
        }

        return  (-1 == r);
    }

}

static std::unique_ptr<geos::geom::Polygon> buildRect4Search(double xWorld,double yWorld,double sizeLngLat,const geos::geom::GeometryFactory *gf)
{

    const std::size_t numPts = 5;
    std::size_t i,j ;
    double x,y,xmin,xmax,ymin,ymax;
    double vs[8];

    xmin = xWorld - sizeLngLat;
    xmax = xWorld + sizeLngLat;
    ymin = yWorld - sizeLngLat;
    ymax = yWorld + sizeLngLat;
    vs[0] = xmin;
    vs[1] = ymin;
    vs[2] = xmin;
    vs[3] = ymax;
    vs[4] = xmax;
    vs[5] = ymax;
    vs[6] = xmax;
    vs[7] = ymin;


    auto coords = geos::detail::make_unique<geos::geom::CoordinateSequence>(numPts);

    i = 0;
    j = 0;

    for(;i < 4; ++i){
        x = vs[j++];
        y = vs[j++];
        coords->setOrdinate(i,0,x);
        coords->setOrdinate(i,1,y);
    }
    x = vs[0];
    y = vs[1];
    coords->setOrdinate(i,0,x);
    coords->setOrdinate(i,1,y);

    std::unique_ptr<geos::geom::LinearRing> shell =  gf->createLinearRing(std::move(coords));

    std::unique_ptr<geos::geom::Polygon> polygon = gf->createPolygon(std::move(shell));
    return polygon;
}

namespace kepen {
namespace core {


RoadLocationLayout::RoadLocationLayout(QWidget *parent, KeSysSetting *conf)
    : QVBoxLayout{parent}
    ,mSysConfig{conf}
{
    setDirection(QBoxLayout::Direction::TopToBottom);
    setSpacing(0);
    setContentsMargins(0, 0, 0, 0);
    setAlignment(Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop);

    mapSurface = dynamic_cast<kepen::core::MapObject*>(parent);


    //Background_BtnOverR2
    QString cssMenBtnAct = QString::asprintf("QPushButton{padding-left:8px; padding-right:8px;padding-top:6px; padding-bottom:6px;background-color:transparent;color:#%08x;border:0px;border-style:none}"
                                             "QPushButton:hover{background-color:#%08x;border-width:1px;border-style:solid;border-color:lightGray;}"
                                             "QPushButton:pressed{background-color: #%08x;}"
                                             ,Color_Font_ToolBar
                                             ,Background_BtnOverR2,Background_BtnDown);
    QString cssLabel = QString::asprintf("QLabel{background-color:transparent;color:#%08x;border:0px;font-size:%dpx;}"
                                         ,Color_Font_Label,TextSize_ToolBar);

    QFont fontLabel;
    fontLabel.setPointSize(TextSize_Tool);

    QWidget *mainBody = new QWidget(parent);
    mainBody->setObjectName("RoadLoactionMainBodyRx");



    QVBoxLayout  *verticalLayout = new QVBoxLayout(mainBody);
    verticalLayout->setObjectName("verticalLayoutMain");
    verticalLayout->setSpacing(0);
    verticalLayout->setContentsMargins(0, 0, 0, 0);
    verticalLayout->setAlignment(Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop);



    QWidget *widget_thiz = new QWidget(mainBody);
    widget_thiz->setObjectName("widget_1");
    QSizePolicy sizePolicy(QSizePolicy::Policy::Preferred, QSizePolicy::Policy::Fixed);
    sizePolicy.setHorizontalStretch(0);
    sizePolicy.setVerticalStretch(0);
    sizePolicy.setHeightForWidth(widget_thiz->sizePolicy().hasHeightForWidth());
    widget_thiz->setSizePolicy(sizePolicy);
    widget_thiz->setMinimumSize(QSize(0, HeightGridItem_Root));






    QHBoxLayout * horizontalLayout_1 = new QHBoxLayout(widget_thiz);

    horizontalLayout_1->setDirection(QBoxLayout::Direction::LeftToRight);
    horizontalLayout_1->setSpacing(0);
    horizontalLayout_1->setContentsMargins(0, 0, 0, 0);
    horizontalLayout_1->setAlignment(Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignVCenter);


    horizontalLayout_1->addSpacerItem(new QSpacerItem(2,HeightSpace, QSizePolicy::Fixed, QSizePolicy::Policy::Minimum));


    QPushButton* btnClose = new QPushButton("\ue634",widget_thiz);


    int fontId = QFontDatabase::addApplicationFont(conf->configView()->fileIconFont);
    QString fontName = QFontDatabase::applicationFontFamilies(fontId).at(0);
    QFont fontIcon = QFont(fontName);
    fontIcon.setPointSize(TextSize_IconFont);


    btnClose->setFont(fontIcon);
    btnClose->setStyleSheet(cssMenBtnAct);

    sizePolicy.setHeightForWidth(btnClose->sizePolicy().hasHeightForWidth());
    btnClose->setSizePolicy(sizePolicy);
    btnClose->setMinimumSize(QSize(38, HeightGridItem_Root));


    horizontalLayout_1->addWidget(btnClose);


    QObject::connect(btnClose, SIGNAL(clicked(bool)),SLOT(onBtnCloseClicked(bool)) );


    horizontalLayout_1->addSpacerItem(new QSpacerItem(2,HeightSpace, QSizePolicy::Fixed, QSizePolicy::Policy::Minimum));


    QString labRoadIdentify("道路查询");
    KeTogLabelIcon* togIdentify = new KeTogLabelIcon(widget_thiz,0xe767U,labRoadIdentify);

    horizontalLayout_1->addWidget(togIdentify);

    horizontalLayout_1->addSpacerItem(new QSpacerItem(2,HeightSpace, QSizePolicy::Fixed, QSizePolicy::Policy::Minimum));

    connect(togIdentify, SIGNAL(toggled(int)),
            this,SLOT(onRoadIdentifyToggled(int)),
            Qt::DirectConnection);


    QPushButton* btnChangeCity = new QPushButton("切换城市",widget_thiz);

    btnChangeCity->setFont(fontLabel);

    btnChangeCity->setStyleSheet(cssMenBtnAct);

    horizontalLayout_1->addWidget(btnChangeCity);
    horizontalLayout_1->addSpacerItem(new QSpacerItem(16,HeightSpace, QSizePolicy::Fixed, QSizePolicy::Policy::Minimum));

    QString currCity = conf->configSQLite()->getCurrCity();
    QLabel * labealA = new QLabel(currCity, widget_thiz);
    labealA->setFont(fontLabel);
    labealA->setStyleSheet(cssLabel);

    horizontalLayout_1->addWidget(labealA);

    horizontalLayout_1->addSpacerItem(new QSpacerItem(20,HeightSpace, QSizePolicy::Fixed, QSizePolicy::Policy::Minimum));



    verticalLayout->addWidget(widget_thiz);


    QWidget *widget_2 = new QWidget(mainBody);
    widget_2->setObjectName("widget_2");
    sizePolicy.setHeightForWidth(widget_2->sizePolicy().hasHeightForWidth());
    widget_2->setSizePolicy(sizePolicy);
    widget_2->setMinimumSize(QSize(0, HeightGridItem_Root));



    QHBoxLayout * horizontalLayout_2 = new QHBoxLayout(widget_2);

    horizontalLayout_2->setDirection(QBoxLayout::Direction::LeftToRight);
    horizontalLayout_2->setSpacing(0);
    horizontalLayout_2->setContentsMargins(0, 0, 0, 0);
    horizontalLayout_2->setAlignment(Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignVCenter);


    horizontalLayout_2->addSpacerItem(new QSpacerItem(LeftPadding,HeightSpace, QSizePolicy::Fixed, QSizePolicy::Policy::Minimum));

    QComboBox* comBox01 =new QComboBox(widget_2);

    comBox01->setFont(fontLabel);
    comBox01->setObjectName("comBox01");
    QSizePolicy sizePolicy1(QSizePolicy::Policy::Fixed, QSizePolicy::Policy::Fixed);
    sizePolicy1.setHorizontalStretch(0);
    sizePolicy1.setVerticalStretch(0);
    sizePolicy1.setHeightForWidth(comBox01->sizePolicy().hasHeightForWidth());
    comBox01->setSizePolicy(sizePolicy1);
    comBox01->setMinimumSize(QSize(MinWidthComboxRx, MinHeightComboxRx));


    horizontalLayout_2->addWidget(comBox01);

    this->m_comBox01 = comBox01;

    horizontalLayout_2->addSpacerItem(new QSpacerItem(4,HeightSpace, QSizePolicy::Fixed, QSizePolicy::Policy::Minimum));






    QPushButton* btnGoRoad = new QPushButton("道路定位",widget_2);

    btnGoRoad->setFont(fontLabel);
    btnGoRoad->setStyleSheet(cssMenBtnAct);

    // sizePolicy.setHeightForWidth(btnGoRoad->sizePolicy().hasHeightForWidth());
    // btnGoRoad->setSizePolicy(sizePolicy);
    // btnGoRoad->setMinimumSize(QSize(0, MinHeightQPushButton));
    // QObject::connect(btnGoRoad, &QPushButton::clicked, [&]() {
    // QMessageBox::information(nullptr, "Button Clicked", "The button was clicked!");
    // });onRoadLocateClicked

    QObject::connect(btnGoRoad, SIGNAL(clicked(bool)),SLOT(onRoadLocateClicked(bool)) );
    horizontalLayout_2->addWidget(btnGoRoad);
    horizontalLayout_2->addSpacerItem(new QSpacerItem(4,HeightSpace, QSizePolicy::Fixed, QSizePolicy::Policy::Minimum));


    verticalLayout->addWidget(widget_2);




    QWidget *widget_3 = new QWidget(mainBody);
    widget_3->setObjectName("widget_3");
    sizePolicy.setHeightForWidth(widget_3->sizePolicy().hasHeightForWidth());
    widget_3->setSizePolicy(sizePolicy);
    widget_3->setMinimumSize(QSize(0, HeightGridItem_Root));




    QHBoxLayout * horizontalLayout_3 = new QHBoxLayout(widget_3);

    horizontalLayout_3->setDirection(QBoxLayout::Direction::LeftToRight);
    horizontalLayout_3->setSpacing(0);
    horizontalLayout_3->setContentsMargins(0, 0, 0, 0);
    horizontalLayout_3->setAlignment(Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignVCenter);

    horizontalLayout_3->addSpacerItem(new QSpacerItem(LeftPadding,HeightSpace, QSizePolicy::Fixed, QSizePolicy::Policy::Minimum));

    QComboBox* comBoxa02 =new QComboBox(widget_3);

    comBoxa02->setFont(fontLabel);

    comBoxa02->setObjectName("comBoxa02");
    sizePolicy1.setHeightForWidth(comBoxa02->sizePolicy().hasHeightForWidth());
    comBoxa02->setSizePolicy(sizePolicy1);
    comBoxa02->setMinimumSize(QSize(MinWidthComboxRx, MinHeightComboxRx));

    horizontalLayout_3->addWidget(comBoxa02);

    horizontalLayout_3->addSpacerItem(new QSpacerItem(4,HeightSpace, QSizePolicy::Fixed, QSizePolicy::Policy::Minimum));

    QPushButton* btnGoRoadCross = new QPushButton("道路交叉口定位",widget_3);

    btnGoRoadCross->setFont(fontLabel);
    btnGoRoadCross->setStyleSheet(cssMenBtnAct);
    horizontalLayout_3->addWidget(btnGoRoadCross);
    horizontalLayout_3->addSpacerItem(new QSpacerItem(4,HeightSpace, QSizePolicy::Fixed, QSizePolicy::Policy::Minimum));

    QObject::connect(btnGoRoadCross, SIGNAL(clicked(bool)),SLOT(onRoadCrossLocateClicked(bool)) );

    verticalLayout->addWidget(widget_3);


    this->m_comBox02 = comBoxa02;

    QSpacerItem *spaceBottom = new QSpacerItem(MinWidthComboxRx,8, QSizePolicy::Fixed, QSizePolicy::Policy::Minimum);
    verticalLayout->addSpacerItem(spaceBottom);






    comBox01->setEditable(true);

    QString cssInput = QCSS_Input();
    QLineEdit* __input = new QLineEdit(widget_thiz);
    __input->setMaxLength(10);
    __input->setStyleSheet(cssInput);
    comBox01->setLineEdit(__input);


    dataContect =NULL;
    comBox01->installEventFilter(this);
    //No such signal QComboBox::QComboBox::activated(int), so ,do not add QComboBox::
    connect(comBox01, SIGNAL(activated(int)), this, SLOT(onActivatedComboBox01(int)));
    /*
    connect(comBox01, &QComboBox::activated, this, [=](int index){
        qDebug() << "用户激活了索引为：" << index << "的项目";
        QString text = m_comBox01->itemText(index);
       QVariant var = m_comBox01->currentData(index);
        kepen::core::GeometryBean* p = (kepen::core::GeometryBean*)var.value<void*>();
       qDebug().noquote() << "项目文本为：" << text <<p->getGeom()->toText();

    });*/
    //connect(ui.stabuyEdit, SIGNAL(returnPressed()), this, SLOT(savestabuyEditinfo()));


    mainBody->setStyleSheet("#RoadLoactionMainBodyRx{border:1px solid #bbb;background:#e4e4dd;}");
    addWidget(mainBody);

    kepen::core::EditWidget*ew = mapSurface->getEditWidgetSingleton();
    ew->clearAllEdit();
    mapSurface->repaint();
}

RoadLocationLayout::~RoadLocationLayout()
{
    if(dataContect)
    {
        delete dataContect;
        dataContect = NULL;
    }

}

void RoadLocationLayout::setSysConfig(KeSysSetting *sysConfig)
{
    mSysConfig = sysConfig;
    initDataSource(sysConfig);
}

void RoadLocationLayout::initDataSource(KeSysSetting *sysConfig)
{
    sqlite3 *dbSQLite3 = sysConfig->configSQLite()->getSQLite3Catch();
    QString tableName = sysConfig->configSQLite()->tableNameRoadLocation();

    if(dataContect)
    {
        delete dataContect;
        dataContect = NULL;
    }

    dataContect = new RoadContext();
    dataContect->initDataSource(dbSQLite3,tableName);

    this->m_comBox01->clear();
    m_comBox02->clear();

    if(dataContect->m_ListRoadName.size()>0)
    {
        std::vector<kepen::kemod::RoadBean*> &v = dataContect->m_ListRoadName;

        sort(v.begin(), v.end(), compare_by_letter);

        for(const auto &bean :v)
        {
            QVariant v_Pointor =  QVariant::fromValue((void *) bean);
            this->m_comBox01->addItem(bean->name,v_Pointor);
        }



        kepen::kemod::RoadBean* p= v.at(0);
        findCrossRoadList(p);
    }
}



bool RoadLocationLayout::eventFilter(QObject *obj, QEvent *event)
{
    if (obj == m_comBox01)
    {
        if (event->type() == QEvent::KeyPress)
        {
            QKeyEvent *ke = static_cast<QKeyEvent*>(event);
            int code = ke->key();
            if (code == Qt::Key_Enter || code == Qt::Key_Return)
            {
                onComboxEditFinshed001();
                return true;
            }
            return false;
        }
        else
        {
            return false;
        }
    }
    return QVBoxLayout::eventFilter(obj, event);
}

void RoadLocationLayout::onComboxEditFinshed001()
{
    QComboBox * &box = m_comBox01;
    QString txt =  box->currentText();
    if(false == (txt.isEmpty() ||txt.isNull()))
    {
        txt = txt.simplified();
    }
    if(txt == this->txtLastInput){
        return;
    }
    this->txtLastInput = txt;

    if( (txt.isEmpty() ||txt.isNull()))
    {
        std::vector<kepen::kemod::RoadBean*> &v = dataContect->m_ListRoadName;
        box->clear();
        for(const auto &bean :v)
        {

            QVariant v_Pointor =  QVariant::fromValue((void *) bean);
            box->addItem(bean->name,v_Pointor);

        }
        box->showPopup();
    }else
    {
        int total = 0,nnn;
        qsizetype lenFieldName, blob_size ;
        ushort *bufChar ;
        std::vector<kepen::kemod::RoadBean*> &v = dataContect->m_ListRoadName;
        box->clear();

        lenFieldName = txt.length();
        blob_size = SizeBuff_Pinyin(lenFieldName);
        bufChar = new ushort[blob_size];

        nnn = KeGetPinyinLatin(txt,Pinyin_separator_Default,bufChar);

        QString py ;
        py.setUtf16(bufChar,nnn);

        delete [] bufChar;


        for(const auto &bean :v)
        {
            if(bean->pinyin.contains(py))
            {
                QVariant v_Pointor =  QVariant::fromValue((void *) bean);
                box->addItem(bean->name,v_Pointor);
                ++total;
            }
        }

        if(0 == total){
            // box->clear();
            for(const auto &bean :v)
            {
                QVariant v_Pointor =  QVariant::fromValue((void *) bean);
                box->addItem(bean->name,v_Pointor);

            }
            box->showPopup();
        }else if(total>0){
            box->showPopup();
        }
    }


}

void RoadLocationLayout::findCrossRoadList(const kepen::kemod::RoadBean *p)
{
    const geos::geom::Geometry* geom = p->geom.get();
    if(geom){
        std::vector<kepen::kemod::RoadBean*> &v = dataContect->m_ListRoadName;
        std::vector<std::unique_ptr<geos::geom::Geometry>> v_buf;
        QComboBox* &box = m_comBox02;
        std::size_t i,  N;
        double  disLng, Meter_cross = MeterBox4Identify;

        box->clear();

        disLng = Meter_cross / OGC_DEGREE_TO_METERS;

        N = geom->getNumGeometries();
        for(i=0;i<N;++i){
            const geos::geom::Geometry* it=geom->getGeometryN(i);
            if(false == it->isEmpty()){
                //E:\open\qt\geos\geos-3.12.1\out\include\geos\operation\buffer\BufferParameters.h
                //BufferParameters EndCapStyle CAP_SQUARE
                std::unique_ptr<geos::geom::Geometry> buf_geom = it->buffer(disLng,6,3);
                v_buf.push_back(std::move(buf_geom));
            }
        }

        if(v_buf.size()>0)
        {
            const geos::geom::Geometry* pGeom;
            for(const auto &bean :v)
            {
                if(p == bean )continue;

                pGeom = bean->geom.get();
                if(pGeom && false == pGeom->isEmpty())
                {
                    for(const auto &g :v_buf){
                        if(g->intersects(pGeom))
                        {
                            QVariant v_Pointor =  QVariant::fromValue((void *) bean);
                            box->addItem(bean->name,v_Pointor);
                            break;
                        }
                    }
                }


            }
        }


    }
}

void RoadLocationLayout::timeoutClose(){
    Q_EMIT onMapLayoutClosed(this);
}

void RoadLocationLayout::onBtnCloseClicked(bool)
{
    kepen::core::MapObject *mapObj = mapSurface;
    kepen::core::EditWidget*ew = mapObj->getEditWidgetSingleton();
    ew->clearAllEdit();
    mapObj->repaint();

    qDebug()  <<__FILE__ <<",Line:"<<__LINE__ ;

     QTimer::singleShot(TimeoutClickFree,this,SLOT(timeoutClose()));
}

void RoadLocationLayout::onRoadIdentifyToggled(int checked)
{
    // qDebug()<<__FILE__<<" Line:"<<__LINE__ <<" param "<<checked;
    kepen::core::MapObject *mapObj = mapSurface;
    mapObj->setActivateTool(NULL);
    if(checked)
    {
        double  meter = MeterBox4IdentifyRoad;
        double sizeLngLat = meter / OGC_DEGREE_TO_METERS;
        BaseMapTool *tool =  mapObj->createToolByBtnID(this,-IdentifyTool_ScreenPoint,false);
        IdentifyPointSimple *identify = dynamic_cast<IdentifyPointSimple*>(tool);
        identify->setSizeLngLat(sizeLngLat);
        connect(identify, SIGNAL(onIdentifyScreenSignals(kepen::core::Point2D)),
                this,SLOT(onIdentifyScreenHandler(kepen::core::Point2D)),
                Qt::DirectConnection);

        mapObj->repaint();
    }else{
        mapObj->setActivateTool(NULL);
        mapObj->repaint();
    }
}

void RoadLocationLayout::onRoadLocateClicked(bool)
{
    int index=  m_comBox01->currentIndex();
    // int index2 =  m_comBox02->currentIndex();
    // qDebug().noquote() << __FILE__ << __LINE__ <<__FUNCTION__  <<index <<"," <<index2;
    QVariant var = m_comBox01->itemData(index);
    const kepen::kemod::RoadBean * p = (const kepen::kemod::RoadBean*)var.value<void*>();
    if(p){
        const geos::geom::Geometry * geom = p->geom.get();
        if(geom && false ==geom->isEmpty())
        {
            kepen::core::MapObject *&mapObj = mapSurface;
            kepen::core::EditWidget*ew = mapObj->getEditWidgetSingleton();

            ew->addHightlight(geom,p->name,HeightlightObj_MultiCircle,Add_Hint_MapView_Truncate);
        }
    }
}

void RoadLocationLayout::onRoadCrossLocateClicked(bool)
{
    int index=  m_comBox01->currentIndex();
    int index2 =  m_comBox02->currentIndex();
    // qDebug().noquote() << __FILE__ << __LINE__ <<__FUNCTION__  <<index <<"," <<index2;
    QVariant varA = m_comBox01->itemData(index);
    QVariant varB = m_comBox02->itemData(index2);
    const kepen::kemod::RoadBean * pA = (const kepen::kemod::RoadBean*)varA.value<void*>();
    const kepen::kemod::RoadBean * pB = (const kepen::kemod::RoadBean*)varB.value<void*>();
    if((pA) && (pB)){
        const geos::geom::Geometry * geomA = pA->geom.get();
        const geos::geom::Geometry * geomB = pB->geom.get();
        if((geomA)
            && false ==geomA->isEmpty()
            &&(geomB)
            && false ==geomB->isEmpty())
        {
            kepen::core::MapObject *&mapObj = mapSurface;
            kepen::core::EditWidget*ew = mapObj->getEditWidgetSingleton();
            AffineTransform worldToScreen;
            std::unique_ptr<Geometry> screenGeomA = geomA->clone();
            std::unique_ptr<Geometry> screenGeomB = geomB->clone();

            mapObj->getWorldToScreen(worldToScreen);
            screenGeomA->apply_rw(&worldToScreen);
            screenGeomB->apply_rw(&worldToScreen);

            std::unique_ptr<geos::geom::CoordinateSequence> vs=
                geos::operation::distance::DistanceOp::nearestPoints(screenGeomA.get(),screenGeomB.get());

            if(vs->size()>1)
            {
                double x0,y0;
                QString szLabel = QString("%1\n%2").arg(pA->name).arg(pB->name);
                x0 = vs->getOrdinate(1,0);
                y0 = vs->getOrdinate(1,1);
                worldToScreen.inverseTransformPoint(&x0,&y0);
                // qDebug().noquote()<<__FILE__<<" Line:"<<__LINE__ <<" addHint: "<<QString::asprintf("(%.6f,%.6f)",x0,y0);
                ew->addHint(szLabel,x0,y0,Type_Hint_MapView_Label,Add_Hint_MapView_Truncate);

            }


        }
    }

}
static
    QPoint getMsgPosition(int x,int y,const QSize &textSize,const QSize &viewSize){
    int  widthText,heightText,left,top,right,bottom,maxRightView ,maxBottomView;

    maxRightView = viewSize.width() - RightPaddingView_Toast;
    maxBottomView  = viewSize.height()- BottomPaddingView_Toast;
    widthText = textSize.width();
    heightText = textSize.height();
    left = x - LeftPadding_Rect_Toast;
    if(left < LeftPaddingView_Toast)
        left = LeftPaddingView_Toast;


    right = left + widthText;
    if(right > maxRightView)
    {
        // qDebug()<<__FILE__<<" Line:"<<__LINE__ <<" param "<<maxRightView<<",right:"<<maxRightView <<"widthText:"<<widthText;
        right = maxRightView ;
        left = right - widthText;

    }

    //default (first)  up
    bottom = y - Heigth_Tri_Toast;
    if(bottom > maxBottomView)bottom = maxBottomView;
    top = bottom - heightText;

    if(top < TopPaddingView_Toast)
    {
        top = y + Heigth_Tri_Toast;
        bottom = top + heightText;
    }

    if(y > top && y < bottom)
    {
        if(bottom < (heightText + 60))
        {
            top = y + Heigth_Tri_Toast;
            // bottom = top + h;
        }else
        {
            bottom = y - Heigth_Tri_Toast;
            top = bottom  - heightText;

        }

    }

    return QPoint(left,top);
}

void RoadLocationLayout::onIdentifyScreenHandler(Point2D ptWorld)
{
    geos::geom::GeometryFactory::Ptr factory = geos::geom::GeometryFactory::create();

    double xWorld,yWorld;

    double  meter = MeterBox4IdentifyRoad;

    double dis,disMin = DBL_MAX, sizeLngLat = meter / OGC_DEGREE_TO_METERS;
    kepen::core::MapObject *mapObj = mapSurface;
    AffineTransform worldToScreen;
    xWorld = ptWorld.x;
    yWorld = ptWorld.y;

    mapObj->getWorldToScreen(worldToScreen);
    // worldToScreen.inverseTransformPoint(&xWorld,&yWorld);

    geos::geom::Coordinate coordWorld(xWorld,yWorld);

    std::unique_ptr<geos::geom::Point> ptrPointWorld = factory->createPoint(coordWorld);

    std::vector<kepen::kemod::RoadBean*> &v = dataContect->m_ListRoadName;

    const geos::geom::Geometry* ptrItGeom;

    kepen::kemod::RoadBean* lpFinded = NULL;


    std::unique_ptr<geos::geom::Polygon> polygon = buildRect4Search(xWorld,yWorld,sizeLngLat,factory.get());

    for(const auto &bean : v)
    {
        ptrItGeom = bean->geom.get();
        if(ptrItGeom && false == ptrItGeom->isEmpty()){
            if(polygon->intersects(ptrItGeom))
            {
                dis = ptrPointWorld->distance(ptrItGeom);
                if(dis <disMin)
                {
                    disMin = dis;
                    lpFinded = bean;
                }
            }
        }
    }


    if(lpFinded)
    {
        int x0,y0;
        double xSnapedWorld,ySnapedWorld;
        PointDistanceResult ppd(Distance_Param_NoBox);
        geos::geom::CoordinateXY xy_world(xWorld,yWorld);
        DistanceBorderByPoint::computeDistance(lpFinded->geom.get(),xy_world,ppd);
        const geos::geom::CoordinateXY &resultPoint = ppd.getCoordinate();
        xSnapedWorld = resultPoint.x;
        ySnapedWorld = resultPoint.y;

        worldToScreen.transformPoint2D(&xSnapedWorld,&ySnapedWorld);

        x0 = qRound(xSnapedWorld);
        y0 = qRound(ySnapedWorld);


        QSize viewSize = mapObj->size();


        QWidget *parent = this->parentWidget();
        KeLabelToast * wPopup = new KeLabelToast(lpFinded->name,parent);
        wPopup->show();
        //after shower(), wPopup->width() can has value
        QSize textSize = wPopup->size();




        QPoint point_t = getMsgPosition(x0,y0,textSize,viewSize);
        QPoint pointGlobal = mapObj->mapToGlobal(point_t);
        wPopup->showAt(4000,pointGlobal);

    }else{
        const kepen::kemod::CityRoadDao * dao = dataContect->getCityRoadDao();
        std::unique_ptr<geos::geom::Geometry> geomEmptyName = dao->identifyEmptyName(polygon.get());
        if(geomEmptyName && geomEmptyName.get())
        {
            int x0,y0;
            double xSnapedWorld,ySnapedWorld;
            PointDistanceResult ppd(Distance_Param_NoBox);

            geos::geom::CoordinateXY xy_world(xWorld,yWorld);

            DistanceBorderByPoint::computeDistance(geomEmptyName.get(),xy_world,ppd);
            const geos::geom::CoordinateXY &resultPoint = ppd.getCoordinate();

            xSnapedWorld = resultPoint.x;
            ySnapedWorld = resultPoint.y;

            worldToScreen.transformPoint2D(&xSnapedWorld,&ySnapedWorld);



            x0 = qRound(xSnapedWorld);
            y0 = qRound(ySnapedWorld);

            QSize viewSize = mapObj->size();


            QWidget *parent = this->parentWidget();
            KeLabelToast * wPopup = new KeLabelToast("无名道路",parent);
            wPopup->show();
            //after shower(), wPopup->width() can has value
            QSize textSize = wPopup->size();






            QPoint point_t = getMsgPosition(x0,y0,textSize,viewSize);
            QPoint pointGlobal = mapObj->mapToGlobal(point_t);
            wPopup->showAt(4000,pointGlobal);

        }else
        {
            double fx,fy;
            int x0,y0;
            QString tip = QString("此位置(%1米范围)没有道路").arg(meter);


            QWidget *parent= this->parentWidget();
            KeLabelToast * wPopup =new KeLabelToast(tip,parent);


            QSize viewSize = mapObj->size();

            fx = ptWorld.x;
            fy = ptWorld.y;
            worldToScreen.transformPoint2D(&fx,&fy);
            x0 = qRound(fx);
            y0 = qRound(fy);

            wPopup->show();
            //after shower(), wPopup->width() can has value
            QSize textSize = wPopup->size();




            QPoint point_t2 = getMsgPosition(x0,y0,textSize,viewSize);

            QPoint pointGlobal = mapObj->mapToGlobal(point_t2);
            wPopup->showAt(4000,pointGlobal);
        }

    }


}

void RoadLocationLayout::onActivatedComboBox01(int index)
{

    // QString text = m_comBox01->itemText(index);
    QVariant var = m_comBox01->itemData(index);
    const kepen::kemod::RoadBean* p = (const kepen::kemod::RoadBean*)var.value<void*>();
    if(p){
        findCrossRoadList(p);
    }

}


}
}
